package nachos.vm;

import java.util.*;

import nachos.machine.*;
import nachos.threads.*;
import nachos.userprog.*;
import nachos.vm.*;

/**
 * A kernel that can support multiple demand-paging user processes.
 */
public class VMKernel extends UserKernel {
	/**
	 * Allocate a new VM kernel.
	 */
	public VMKernel() {
		super();
	}

	/**
	 * Initialize this kernel.
	 */
	public void initialize(String[] args) {
		super.initialize(args);
		
		//initialize the swapFile
		swapFile = createSwapFile();
		swapFileWrite(0, "You found the hidden message! You get a cookie!".getBytes());
		
		//initialize the pinTable
		for (int i = 0; i < Machine.processor().getNumPhysPages();i++)
			pinTable[i] = new Lock();
	}

	/**
	 * Test this kernel.
	 */
	public void selfTest() {
		super.selfTest();
	}

	/**
	 * Start running user programs.
	 */
	public void run() {
		super.run();
	}

	/**
	 * Terminate this kernel. Never returns.
	 */
	public void terminate() {
		swapFile.close();
		deleteSwapFile();
		super.terminate();
	}

	private static final int pageSize = Processor.pageSize;

	/** Converts a SwapPage number into a file offset */
	public static int spNumToOffset(int spNum) {
		return spNum * pageSize;
	}

	/** The free swappages list. */
	public static Vector freeSwapPages = new Vector();
	/** The next SwapPage if the swapfile is full */
	public static int nextSwapPage = 0;
	/** The filename for the swapfile */
	public static String swapFileName = "Jabberwocky.swap";

	public static OpenFile swapFile;

	private OpenFile createSwapFile() {

		OpenFile swapFile = ThreadedKernel.fileSystem.open(swapFileName, true);
		return swapFile;
	}

	private static int deleteSwapFile() {
		if (!ThreadedKernel.fileSystem.remove(swapFileName))
			return -1;
		return 0;
	}

	public static int swapFileWrite(int swapPageNum, byte[] page) {
		if (swapPageNum > nextSwapPage)
		return -1;
		int pos = spNumToOffset(swapPageNum);
		return swapFile.write(pos, page, 0, page.length);
	}

	public static int swapFileRead(int swapPageNum, byte[] page) {
		if (swapPageNum >= nextSwapPage)
			return -1;
		int pos = spNumToOffset(swapPageNum);
		return swapFile.read(pos, page, 0, page.length);
	}

	public static final Lock[] pinTable = new Lock[Machine.processor().getNumPhysPages()];
	public static final VMProcess[] invertedPageTable = new VMProcess[Machine
			.processor().getNumPhysPages()];
	// dummy variables to make javac smarter
	private static VMProcess dummy1 = null;

	private static final char dbgVM = 'v';
}
